import NodeIdFactory
from NodeIdType import *
from base import BitsLong
from NodeIdInline import NodeIdInline

'''
 * 
 * @param v long
 * @return NodeId
'''
def makeSpecial(v):
    # Careful of an initializer loop (create(type, v1, v2) looks at specials).
    return NodeIdFactory.createValue(NodeIdType.SPECIAL, v)

'''
 * 
 * @param nodeId NodeId
 * @return boolean
'''
def isInlineInner(nodeId):
    return NodeIdType.isInline(nodeId.type)


# Migration

'''
 * 
 * @param node Node
 * @return NodeId
'''
def inline(node):
    return NodeIdInline.inline(node)


#    public long getPtrLocation(): return value2 
#    public long getPtrLo(): return value2 
#    public int  getPtrHi(): return value1 & 0x00FFFFFF 

'''
 * 
 * @param node Node
 * @return boolean
'''
def hasInlineDatatype(node):
    return NodeIdInline.hasInlineDatatype(node)

# Long.
#    public long getPtrLo()         : return value2 
#    public int  getPtrHi()         : return value1 

'''
 * 
 * @param nodeId NodeId
 * @return Node
'''
def extract(nodeId):
    return NodeIdInline.extract(nodeId)


# XXX Later.
#    #Static forms only?
#    public boolean isAny()         : return isAny(this) 
#    public boolean isDoesNotExist(): return isDoesNotExist(this) 
#    public boolean isDefined()     : return isDefined(this) 
#    public boolean isUndefined()   : return isDefined(this) 
#

'''
 * 
 * @param nodeId NodeId
 * @return boolean
'''
def isAny(nodeId):
    return nodeId == NodeId.NodeIdAny or nodeId is None


'''
 * 
 * @param nodeId NodeId
 * @return boolean
'''
def isDoesNotExist(nodeId):
    return nodeId == NodeId.NodeDoesNotExist


'''
 * Create from a long-encoded value
 * @param type NodeIdType
 * @param value long
 * @return NodeId
'''

def createRaw(type, value):
    return NodeId(type, 0, value)


'''
 * Create from a (int,long)-encoded value
 * @param type  NodeIdType
 * @param value1 int
 * @param value2 long
 * @return NodeId
'''

def createRaw2(type, value1, value2):
    return NodeId(type, value1, value2)


'''
 * 
 * @param nodeId NodeId
 * @param v1 int
 * @param v2 long
 * @return boolean
'''

def equals3(nodeId, v1, v2):
    return v2 == nodeId.value2 and v1 == nodeId.value1


'''
 * Compare - provides an ordering of:@code NodeIds.
 * @param n1 NodeId
 * @param n2 NodeId
 * @return int
'''
def compare(n1, n2):
    # int
    # Integer.compare(n1.value1, n2.value1)
    x = 0
    if n1.value1 > n2.value1:
        x = 1
    elif n1.value1 < n2.value1:
        x = -1
    if (x == 0):
        #return CMP_EQUAL
        return 0
    return compare(n1.value2, n2.value2)


'''
 * @param nodeId NodeId
 * @return boolean
'''
def isConcrete(nodeId):
    return not NodeIdType.isSpecial(nodeId.type)
    

class NodeId:

    SIZE = 8
    NodeIdInvalid = makeSpecial(0xA1)
    NodeDoesNotExist = makeSpecial(0xA3)
    NodeIdAny = makeSpecial(0xA4)
    NodeIdDefined = makeSpecial(0xA5)
    NodeIdUndefined = makeSpecial(0xA6)

    def __init__(self, type, v1, v2):
        self.check(type, v1, v2)
        self.type = type
        self.value1 = v1
        self.value2 = v2

    '''
     *
     * @param type NodeIdType
     * @param v1 int
     * @param v2 int
     * @return void
    '''
    def check(self, type, v1, v2):
        if (type == NodeIdType.PTR):
            return
        if (type == NodeIdType.SPECIAL):
            return
        # 64 bit NodeId.
        x = BitsLong.unpack(v2, 56, 64)
        if (type == NodeIdType.XSD_DOUBLE):
            x = BitsLong.unpack(v2, 62, 64)
        if (x != 0):
            print(f"Type set in long: type={type} value={v2}")

    def getPtrLocation(self):
        return self.value2

    def getTypeValue(self):
        return self.type.type()

    def isInline(self):
        return isInlineInner(self)

    def isValue(self):
        return self.type != NodeIdType.PTR and NodeIdType.isStorable(self.type)

    def type(self):
        return self.type

    def getValue1(self):
        return self.value1

    def getValue2(self):
        return self.value2

'''
hashCode
equals
equals2
toString
compareTo
'''

def equals(nodeId, v1, v2):
    pass


